using System.Runtime.InteropServices;

namespace FinMkts.Messaging.Pgm
{
    [StructLayout(LayoutKind.Sequential)]
    public class RmReceiverStats
    {
        // this might look odd as there is no way of setting these fields
        // but the fields are set by the marhsalling code when we get the data from the socket
        private ulong _oDataPacketsReceived;
        private ulong _rDataPacketsReceived;
        private ulong _duplicateDataPackets;
        private ulong _dataBytesReceived;
        private ulong _totalBytesReceived;
        private ulong _rateKBitsPerSecOverall;
        private ulong _rateKBitsPerSecLast;
        private ulong _trailingEdgeSeqId;
        private ulong _leadingEdgeSeqId;
        private ulong _averageSequencesInWindow;
        private ulong _minSequencesInWindow;
        private ulong _maxSequencesInWindow;
        private ulong _firstNakSequenceNumber;
        private ulong _pendingNaks;
        private ulong _outstandingNaks;
        private ulong _dataPacketsBuffered;
        private ulong _totalSelectiveNaksSent;
        private ulong _totalParityNaksSent;

        /// <summary>
        /// # OData sequences received
        /// </summary>
        public ulong ODataPacketsReceived
        {
            get { return _oDataPacketsReceived; }
        }

        /// <summary>
        /// # RData sequences received
        /// </summary>
        public ulong RDataPacketsReceived
        {
            get { return _rDataPacketsReceived; }
        }

        /// <summary>
        /// # RData sequences received
        /// </summary>
        public ulong DuplicateDataPackets
        {
            get { return _duplicateDataPackets; }
        }

        /// <summary>
        /// # client data bytes received out so far
        /// </summary>
        public BinarySize ClientDataReceived
        {
            get { return BinarySize.FromBytes(_dataBytesReceived); }
        }

        /// <summary>
        /// SPM, OData and RData bytes
        /// </summary>
        public BinarySize TotalDataReceived
        {
            get { return BinarySize.FromBytes(_totalBytesReceived); }
        }

        /// <summary>
        /// Internally calculated Receive-rate from the beginning
        /// </summary>
        public BinarySize RatePerSecOverall
        {
            get { return BinarySize.FromKiloBits(_rateKBitsPerSecOverall); }
        }

        /// <summary>
        /// Receive-rate calculated every INTERNAL_RATE_CALCULATION_FREQUENCY
        /// </summary>
        public BinarySize RatePerSecLast
        {
            get { return BinarySize.FromKiloBits(_rateKBitsPerSecLast); }
        }

        /// <summary>
        /// smallest (oldest) Sequence Id in the window
        /// </summary>
        public ulong TrailingEdgeSeqId
        {
            get { return _trailingEdgeSeqId; }
        }

        /// <summary>
        /// largest (newest) Sequence Id in the window
        /// </summary>
        public ulong LeadingEdgeSeqId
        {
            get { return _leadingEdgeSeqId; }
        }

        public ulong AverageSequencesInWindow
        {
            get { return _averageSequencesInWindow; }
        }

        public ulong MinSequencesInWindow
        {
            get { return _minSequencesInWindow; }
        }

        public ulong MaxSequencesInWindow
        {
            get { return _maxSequencesInWindow; }
        }

        /// <summary>
        /// # First Outstanding Nak
        /// </summary>
        public ulong FirstNakSequenceNumber
        {
            get { return _firstNakSequenceNumber; }
        }

        /// <summary>
        /// # Sequences waiting for Ncfs
        /// </summary>
        public ulong PendingNaks
        {
            get { return _pendingNaks; }
        }

        /// <summary>
        /// # Sequences for which Ncfs have been received, but no data
        /// </summary>
        public ulong OutstandingNaks
        {
            get { return _outstandingNaks; }
        }

        /// <summary>
        /// # Data packets currently buffered by transport
        /// </summary>
        public ulong DataPacketsBuffered
        {
            get { return _dataPacketsBuffered; }
        }

        /// <summary>
        /// # Selective NAKs sent so far
        /// </summary>
        public ulong TotalSelectiveNaksSent
        {
            get { return _totalSelectiveNaksSent; }
        }

        /// <summary>
        /// # Parity NAKs sent so far
        /// </summary>
        public ulong TotalParityNaksSent
        {
            get { return _totalParityNaksSent; }
        }

        public override string ToString()
        {
            return string.Format("ODataPacketsReceived: {0}, RDataPacketsReceived: {1}, DuplicateDataPackets: {2}, ClientDataReceived: {3}, TotalDataReceived: {4}, RatePerSecOverall: {5}, RatePerSecLast: {6}, TrailingEdgeSeqId: {7}, LeadingEdgeSeqId: {8}, AverageSequencesInWindow: {9}, MinSequencesInWindow: {10}, MaxSequencesInWindow: {11}, FirstNakSequenceNumber: {12}, PendingNaks: {13}, OutstandingNaks: {14}, DataPacketsBuffered: {15}, TotalSelectiveNaksSent: {16}, TotalParityNaksSent: {17}", 
                ODataPacketsReceived, RDataPacketsReceived, DuplicateDataPackets, 
                ClientDataReceived, TotalDataReceived,
                RatePerSecOverall.ToString(BitsBytes.Bits), RatePerSecLast.ToString(BitsBytes.Bits), 
                _trailingEdgeSeqId, _leadingEdgeSeqId, _averageSequencesInWindow, 
                _minSequencesInWindow, _maxSequencesInWindow, 
                _firstNakSequenceNumber, _pendingNaks, _outstandingNaks, 
                _dataPacketsBuffered, _totalSelectiveNaksSent, _totalParityNaksSent);
        }
    }
}